package com.crazymakercircle.imServer.distributed;

import com.crazymakercircle.imServer.server.ServerConstants;
import com.crazymakercircle.imServer.zk.ZKclient;
import com.crazymakercircle.util.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.ChildData;
import org.apache.curator.framework.recipes.cache.TreeCache;
import org.apache.curator.framework.recipes.cache.TreeCacheEvent;
import org.apache.curator.framework.recipes.cache.TreeCacheListener;

import java.util.concurrent.ConcurrentHashMap;

/**
 * IM路由器WorkerRouter
 * create by 尼恩 @ 疯狂创客圈
 **/
@Slf4j
public class WorkerRouter {
    //Zk客户端
    private CuratorFramework client = null;

    //单例模式
    private static WorkerRouter singleInstance = null;
    //监听路径
    private static final String path = ServerConstants.MANAGE_PATH;
    //节点的容器
    private ConcurrentHashMap<Long, WorkerReSender> workerMap =
            new ConcurrentHashMap<>();


    public static WorkerRouter getInst() {
        if (null == singleInstance) {
            singleInstance = new WorkerRouter();
            singleInstance.client = ZKclient.instance.getClient();
            singleInstance.init();
        }
        return singleInstance;
    }

    private WorkerRouter() {

    }

    //WorkerRouter 初始化代码
    private void init() {
        try {

            //订阅节点的增加和删除事件
            TreeCache treeCache = new TreeCache(client, path);
            TreeCacheListener l = new TreeCacheListener() {
                @Override
                public void childEvent(CuratorFramework client,
                                       TreeCacheEvent event) throws Exception {
                    ChildData data = event.getData();
                    if (data != null) {
                        switch (event.getType()) {
                            case NODE_REMOVED:
                                processNodeRemoved(data);

                                break;

                            case NODE_ADDED:
                                processNodeAdded(data);

                                break;
                            default:
                                break;
                        }
                    } else {
                        log.info("[TreeCache]节点数据为空, path={}", data.getPath());
                    }
                }
            };

            treeCache.getListenable().addListener(l);
            treeCache.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    private void processNodeRemoved(ChildData data) {

        log.info("[TreeCache]节点删除, path={}, data={}",
                data.getPath(), data.getData());
        byte[] payload = data.getData();
        ImNode n = JsonUtil.JsonBytes2Object(payload, ImNode.class);

        WorkerReSender peerSender = workerMap.get(n.getId());

        if (null != peerSender) {
            peerSender.stopConnecting();
            workerMap.remove(n.getId());
        }


    }

    /**
     * 节点增加的处理
     * @param data 新节点
     */
    private void processNodeAdded(ChildData data) {
        log.info("[TreeCache]节点更新端口, path={}, data={}",
                data.getPath(), data.getData());
        byte[] payload = data.getData();
        String path = data.getPath();
        ImNode imNode =
                JsonUtil.JsonBytes2Object(payload, ImNode.class);
        long id = getId(path);
        imNode.setId(id);

        WorkerReSender reSender = workerMap.get(imNode.getId());
        //重复收到注册的事件
        if (null != reSender && reSender.getRemoteNode().equals(imNode)) {
            return;
        }

        //创建一个消息转发器
        reSender = new WorkerReSender(imNode);
        //建立转发的连接
        reSender.doConnect();

        workerMap.put(id, reSender);
    }


    public WorkerReSender getRedirectSender(long id) {
        WorkerReSender peerSender = workerMap.get(id);
        if (null != peerSender) {
            return peerSender;
        }
        return null;
    }


    public long getId(String nodePath) {
        String sid = null;
        if (null == nodePath) {
            throw new RuntimeException("节点注册失败");
        }
        int index = nodePath.lastIndexOf(ServerConstants.PATH_PREFIX);
        if (index >= 0) {
            index += ServerConstants.PATH_PREFIX.length();
            sid = index <= nodePath.length() ? nodePath.substring(index) : null;
        }

        if (null == sid) {
            throw new RuntimeException("节点ID生成失败");
        }

        return Long.parseLong(sid);

    }

    public void removeWorkerById(ImNode node) {

    }
}
